<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.5.2" />
<title></title>
<style type="text/css">
/* Debug borders */
p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
/*
  border: 1px solid red;
*/
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

tt {
  color: navy;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  font-family: sans-serif;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}

div.sectionbody {
  font-family: serif;
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}

pre {
  padding: 0;
  margin: 0;
}

span#author {
  color: #527bbd;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 1.1em;
}
span#email {
}
span#revnumber, span#revdate, span#revremark {
  font-family: sans-serif;
}

div#footer {
  font-family: sans-serif;
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
div#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
div#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

div#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-family: sans-serif;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid silver;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid silver;
  background: #f4f4f4;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #dddddd;
  color: #777777;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > div.content {
  white-space: pre;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-family: sans-serif;
  font-weight: bold;
}
tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}


@media print {
  div#footer-badges { display: none; }
}

div#toc {
  margin-bottom: 2.5em;
}

div#toctitle {
  color: #527bbd;
  font-family: sans-serif;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}
/* Workarounds for IE6's broken and incomplete CSS2. */

div.sidebar-content {
  background: #ffffee;
  border: 1px solid silver;
  padding: 0.5em;
}
div.sidebar-title, div.image-title {
  color: #527bbd;
  font-family: sans-serif;
  font-weight: bold;
  margin-top: 0.0em;
  margin-bottom: 0.5em;
}

div.listingblock div.content {
  border: 1px solid silver;
  background: #f4f4f4;
  padding: 0.5em;
}

div.quoteblock-attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock-content {
  white-space: pre;
}
div.verseblock-attribution {
  padding-top: 0.75em;
  text-align: left;
}

div.exampleblock-content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

/* IE6 sets dynamically generated links as visited. */
div#toc a:visited { color: blue; }
</style>
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes();}
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  var cont = document.getElementById("content");
  var noteholder = document.getElementById("footnotes");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      // Use [\s\S] in place of . so multi-line matches work.
      // Because JavaScript has no s (dotall) regex flag.
      note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      spans[i].innerHTML =
        "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
        "' title='View footnote' class='footnote'>" + n + "</a>]";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
}

}
/*]]>*/
</script>
</head>
<body>
<div id="header">
</div>
<div id="content">

<h2 id="_bufferevents_concepts_and_basics">Bufferevents: concepts and basics</h2>
<div class="sectionbody">
<div class="paragraph"><p>Most of the time, an application wants to perform some amount of data
buffering in addition to just responding to events.  When we want to
write data, for example, the usual pattern runs something like:</p></div>
<div class="ulist"><ul>
<li>
<p>
Decide that we want to write some data to a connection; put that
  data in a buffer.
</p>
</li>
<li>
<p>
Wait for the connection to become writable
</p>
</li>
<li>
<p>
Write as much of the data as we can
</p>
</li>
<li>
<p>
Remember how much we wrote, and if we still have more data to write,
  wait for the connection to become writable again.
</p>
</li>
</ul></div>
<div class="paragraph"><p>This buffered IO pattern is common enough that Libevent provides a
generic mechanism for it.  A "bufferevent" consists of an
underlying transport (like a socket), a read buffer, and a write
buffer.  Instead of regular events, which give callbacks when the
underlying transport is ready to be read or written, a bufferevent
invokes its user-supplied callbacks when it has read or written enough
data.</p></div>
<div class="paragraph"><p>There are multiple types of bufferevent that all share a common
interface.  As of this writing, the following types exist:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
socket-based bufferevents
</dt>
<dd>
<p>
    A bufferevent that sends and receives data from an underlying
    stream socket, using the event_* interface as its backend.
</p>
</dd>
<dt class="hdlist1">
asynchronous-IO bufferevents
</dt>
<dd>
<p>
    A bufferevent that uses the Windows IOCP interface to send and
    receive data to an underlying stream socket.  (Windows only;
    experimental.)
</p>
</dd>
<dt class="hdlist1">
filtering bufferevents
</dt>
<dd>
<p>
    A bufferevent that processes incoming and outgoing data before
    passing it to an underlying bufferevent object&#8212;for example, to
    compress or translate data.
</p>
</dd>
<dt class="hdlist1">
paired bufferevents
</dt>
<dd>
<p>
    Two bufferevents that transmit data to one another.
</p>
</dd>
</dl></div>
<div class="paragraph"><div class="title">NOTE</div><p>As of Libevent 2.0.2-alpha, the bufferevents interfaces here are still
not fully orthogonal across all bufferevent types.  In other words,
not every interface described below will work on all bufferevent types.
The Libevent developers intend to correct this in future versions.</p></div>
<div class="paragraph"><div class="title">NOTE ALSO</div><p>Bufferevents currently only work for stream-oriented protocols like TCP.
There may in the future be support for datagram-oriented protocols like UDP.</p></div>
<div class="paragraph"><p>All of the functions and types in this section are declared in
event2/bufferevent.h.  Functions specifically related to evbuffers are
declared in event2/buffer.h; see the next chapter for information on
those.</p></div>
<h3 id="_bufferevents_and_evbuffers">Bufferevents and evbuffers</h3><div style="clear:left"></div>
<div class="paragraph"><p>Every bufferevent has an input buffer and an output buffer.  These are
of type "struct evbuffer".  When you have data to write on a
bufferevent, you add it to the output buffer; when a bufferevent has
data for you to read, you drain it from the input buffer.</p></div>
<div class="paragraph"><p>The evbuffer interface supports many operations; we discuss them in a
later section.</p></div>
<h3 id="_callbacks_and_watermarks">Callbacks and watermarks</h3><div style="clear:left"></div>
<div class="paragraph"><p>Every bufferevent has two data-related callbacks: a read callback
and a write callback.  By default, the read callback is called
whenever any data is read from the underlying transport, and the write
callback is called whenever enough data from the output buffer is emptied to
the underlying transport.  You can override the behavior of these functions
by adjusting the read and write "watermarks" of the bufferevent.</p></div>
<div class="paragraph"><p>Every bufferevent has four watermarks:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
Read low-water mark
</dt>
<dd>
<p>
   Whenever a read occurs that leaves the bufferevent&#8217;s input buffer
   at this level or higher, the bufferevent&#8217;s read callback is invoked.
   Defaults to 0, so that every read results in the read callback
   being invoked.
</p>
</dd>
<dt class="hdlist1">
Read high-water mark
</dt>
<dd>
<p>
   If the bufferevent&#8217;s input buffer ever gets to this level, the
   bufferevent stops reading until enough data is drained from the
   input buffer to take us below it again.  Defaults to unlimited, so
   that we never stop reading because of the size of the input buffer.
</p>
</dd>
<dt class="hdlist1">
Write low-water mark
</dt>
<dd>
<p>
   Whenever a write occurs that takes us to this level or below, we
   invoke the write callback.  Defaults to 0, so that a write callback
   is not invoked unless the output buffer is emptied.
</p>
</dd>
<dt class="hdlist1">
Write high-water mark
</dt>
<dd>
<p>
   Not used by a bufferevent directly, this watermark can have special
   meaning when a bufferevent is used as the underlying transport of
   another bufferevent.  See notes on filtering bufferevents below.
</p>
</dd>
</dl></div>
<div class="paragraph"><p>A bufferevent also has an "error" or "event" callback that gets
invoked to tell the application about non-data-oriented events, like
when a connection is closed or an error occurs.  The following event
flags are defined:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
BEV_EVENT_READING
</dt>
<dd>
<p>
   An event occured during a read operation on the bufferevent.  See
   the other flags for which event it was.
</p>
</dd>
<dt class="hdlist1">
BEV_EVENT_WRITING
</dt>
<dd>
<p>
   An event occured during a write operation on the bufferevent.  See
   the other flags for which event it was.
</p>
</dd>
<dt class="hdlist1">
BEV_EVENT_ERROR
</dt>
<dd>
<p>
   An error occurred during a bufferevent operation.  For more
   information on what the error was, call EVUTIL_SOCKET_ERROR().
</p>
</dd>
<dt class="hdlist1">
BEV_EVENT_TIMEOUT
</dt>
<dd>
<p>
   A timeout expired on the bufferevent.
</p>
</dd>
<dt class="hdlist1">
BEV_EVENT_EOF
</dt>
<dd>
<p>
   We got an end-of-file indication on the bufferevent.
</p>
</dd>
<dt class="hdlist1">
BEV_EVENT_CONNECTED
</dt>
<dd>
<p>
   We finished a requested connection on the bufferevent.
</p>
</dd>
</dl></div>
<div class="paragraph"><p>(The above event names are new in Libevent 2.0.2-alpha.)</p></div>
<h3 id="_deferred_callbacks">Deferred callbacks</h3><div style="clear:left"></div>
<div class="paragraph"><p>By default, a bufferevent callbacks are executed <em>immediately</em> when
the corresponding condition happens.  (This is true of evbuffer
callbacks too; we&#8217;ll get to those later.)  This immediate invocation
can make trouble when dependencies get complex.  For example, suppose
that there is a callback that moves data into evbuffer A when it grows
empty, and another callback that processes data out of evbuffer A when
it grows full.  Since these calls are all happening on the stack, you
might risk a stack overflow if the dependency grows nasty enough.</p></div>
<div class="paragraph"><p>To solve this, you can tell a bufferevent (or an evbuffer) that its
callbacks should be <em>deferred</em>.  When the conditions are met for a
deferred callback, rather than invoking it immediately, it is queued
as part of the event_loop() call, and invoked after  the regular events'
callbacks.</p></div>
<div class="paragraph"><p>(Deferred callbacks were introduced in Libevent 2.0.1-alpha.)</p></div>
<h3 id="_option_flags_for_bufferevents">Option flags for bufferevents</h3><div style="clear:left"></div>
<div class="paragraph"><p>You can use one or more flags when creating a bufferevent to alter its
behavior.  Recognized flags are:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
BEV_OPT_CLOSE_ON_FREE
</dt>
<dd>
<p>
    When the bufferevent is freed, close the underlying transport.
    This will close an underlying socket, free an underlying
    bufferevent, etc.
</p>
</dd>
<dt class="hdlist1">
BEV_OPT_THREADSAFE
</dt>
<dd>
<p>
    Automatically allocate locks for the bufferevent, so that it&#8217;s
    safe to use from multiple threads.
</p>
</dd>
<dt class="hdlist1">
BEV_OPT_DEFER_CALLBACKS
</dt>
<dd>
<p>
    When this flag is set, the bufferevent defers all of its callbacks,
    as described above.
</p>
</dd>
<dt class="hdlist1">
BEV_OPT_UNLOCK_CALLBACKS
</dt>
<dd>
<p>
    By default, when the bufferevent is set up to be threadsafe, the
    bufferevent&#8217;s locks are held whenever the any user-provided
    callback is invoked.  Setting this option makes Libevent release
    the bufferevent&#8217;s lock when it&#8217;s invoking your callbacks.
</p>
</dd>
</dl></div>
<div class="paragraph"><p>(Libevent 2.0.5-beta introduced BEV_OPT_UNLOCK_CALLBACKS.  The other options
above were new in Libevent 2.0.1-alpha.)</p></div>
<h3 id="_working_with_socket_based_bufferevents">Working with socket-based bufferevents</h3><div style="clear:left"></div>
<div class="paragraph"><p>The simplest bufferevents to work with is the socket-based type.  A
socket-based bufferevent uses Libevent&#8217;s underlying event mechanism to
detect when an underlying network socket is ready for read and/or write
operations, and uses underlying network calls (like readv, writev,
WSASend, or WSARecv) to transmit and receive data.</p></div>
<h4 id="_creating_a_socket_based_bufferevent">Creating a socket-based bufferevent</h4>
<div class="paragraph"><p>You can create a socket-based bufferevent using
bufferevent_socket_new():</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>struct</strong> bufferevent *bufferevent_socket_new(
    <strong>struct</strong> event_base *base,
    evutil_socket_t fd,
    <strong>enum</strong> bufferevent_options options);</tt></pre>
</div></div>
<div class="paragraph"><p>The <em>base</em> is an event_base, and <em>options</em> is a bitmask of bufferevent
options (BEV_OPT_CLOSE_ON_FREE, etc).  The <em>fd</em> argument is an
optional file descriptor for a socket.  You can set fd to -1 if
you want to set the file descriptor later.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">[Make sure that the socket you provide to bufferevent_socket_new is
in non-blocking mode. Libevent provides the convenience method
evutil_make_socket_nonblocking for this.]</td>
</tr></table>
</div>
<div class="paragraph"><p>This function returns a bufferevent on success, and NULL on failure.</p></div>
<div class="paragraph"><p>The bufferevent_socket_new() function was introduced in Libevent 2.0.1-alpha.</p></div>
<h4 id="_launching_connections_on_socket_based_bufferevents">Launching connections on socket-based bufferevents</h4>
<div class="paragraph"><p>If the bufferevent&#8217;s socket is not yet connected, you can launch a new
connection.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>int</strong> bufferevent_socket_connect(<strong>struct</strong> bufferevent *bev,
    <strong>struct</strong> sockaddr *address, <strong>int</strong> addrlen);</tt></pre>
</div></div>
<div class="paragraph"><p>The address and addrlen arguments are as for the standard call
connect().  If the bufferevent does not already have a socket set,
calling this function allocates a new stream socket for it, and makes
it nonblocking.</p></div>
<div class="paragraph"><p>If the bufferevent <strong>does</strong> have a socket already, calling
bufferevent_socket_connect() tells Libevent that the socket is not
connected, and no reads or writes should be done on the socket until
the connect operation has succeeded.</p></div>
<div class="paragraph"><p>It is okay to add data to the output buffer before the connect is
done.</p></div>
<div class="paragraph"><p>This function returns 0 if the connect was successfully launched, and
-1 if an error occurred.</p></div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre><tt>#include &lt;event2/event.h&gt;
#include &lt;event2/bufferevent.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;string.h&gt;

<strong>void</strong> eventcb(<strong>struct</strong> bufferevent *bev, <strong>short</strong> events, <strong>void</strong> *ptr)
{
    <strong>if</strong> (events &amp; BEV_EVENT_CONNECTED) {
<i>         /* We're connected to 127.0.0.1:8080.   Ordinarily we'd do</i>
<i>            something here, like start reading or writing. */</i>
    } <strong>else</strong> <strong>if</strong> (events &amp; BEV_EVENT_ERROR) {
<i>         /* An error occured while connecting. */</i>
    }
}

<strong>int</strong> main_loop(<strong>void</strong>)
{
    <strong>struct</strong> event_base *base;
    <strong>struct</strong> bufferevent *bev;
    <strong>struct</strong> sockaddr_in sin;

    base = event_base_new();

    memset(&amp;sin, 0, <strong>sizeof</strong>(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
    sin.sin_port = htons(8080); /* Port 8080 */

    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);

    bufferevent_setcb(bev, NULL, NULL, eventcb, NULL);

    <strong>if</strong> (bufferevent_socket_connect(bev,
        (<strong>struct</strong> sockaddr *)&amp;sin, <strong>sizeof</strong>(sin)) &lt; 0) {
<i>        /* Error starting connection */</i>
        bufferevent_free(bev);
        <strong>return</strong> -1;
    }

    event_base_dispatch(base);
    <strong>return</strong> 0;
}</tt></pre>
</div></div>
<div class="paragraph"><p>The bufferevent_base_connect() function was introduced in
Libevent-2.0.2-alpha.  Before then, you had to manually call
connect() on your socket yourself, and when the connection was
complete, the bufferevent would report it as a write.</p></div>
<div class="paragraph"><p>Note that you only get a BEV_EVENT_CONNECTED event if you launch the
connect() attempt using bufferevent_socket_connect().  If you call
connect() on your own, the connection gets reported as a write.</p></div>
<div class="paragraph"><p>If you want to call connect() yourself, but still get receive a
BEV_EVENT_CONNECTED event when the connection succeeds, call
bufferevent_socket_connect(bev, NULL, 0) after connect() returns -1 with
errno equal to EAGAIN or EINPROGRESS.</p></div>
<div class="paragraph"><p>This function was introduced in Libevent 2.0.2-alpha.</p></div>
<h4 id="_launching_connections_by_hostname">Launching connections by hostname</h4>
<div class="paragraph"><p>Quite often, you&#8217;d like to combine resolving a hostname and connecting to it
into a single operation.  There&#8217;s an interface for that:</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>int</strong> bufferevent_socket_connect_hostname(<strong>struct</strong> bufferevent *bev,
    <strong>struct</strong> evdns_base *dns_base, <strong>int</strong> family, <strong>const</strong> <strong>char</strong> *hostname,
    <strong>int</strong> port);
<strong>int</strong> bufferevent_socket_get_dns_error(<strong>struct</strong> bufferevent *bev);</tt></pre>
</div></div>
<div class="paragraph"><p>This function resolves the DNS name <em>hostname</em>, looking for addresses of type
<em>family</em>.  (Allowable family types are AF_INET, AF_INET6, and AF_UNSPEC.)  If
the name resolution fails, it invokes the event callback with an error event.
If it succeeds, it launches a connection attempt just as bufferevent_connect
would.</p></div>
<div class="paragraph"><p>The dns_base argument is optional.  If it is NULL, then Libevent blocks while
waiting for the name lookup to finish, which usually isn&#8217;t what you want.  If
it is provided, then Libevent uses it to look up the hostname asynchronously.
See <a href="Ref9_dns.html">chapter R9</a> for more info on DNS.</p></div>
<div class="paragraph"><p>As with bufferevent_socket_connect(), this function tells Libevent that any
existing socket on the bufferevent is not connected, and no reads or writes
should be done on the socket until the resolve is finished and the connect
operation has succeeded.</p></div>
<div class="paragraph"><p>If an error occurs, it might be a DNS hostname lookup error.  You can find
out what the most recent error was by calling
bufferevent_socket_get_dns_error().  If the returned error code is 0, no DNS
error was detected.</p></div>
<div class="listingblock">
<div class="title">Example: Trivial HTTP v0 client.</div>
<div class="content">
<pre><tt><i>/* Don't actually copy this code: it is a poor way to implement an</i>
<i>   HTTP client.  Have a look at evhttp instead.</i>
<i>*/</i>
#include &lt;event2/dns.h&gt;
#include &lt;event2/bufferevent.h&gt;
#include &lt;event2/buffer.h&gt;
#include &lt;event2/util.h&gt;
#include &lt;event2/event.h&gt;

#include &lt;stdio.h&gt;

<strong>void</strong> readcb(<strong>struct</strong> bufferevent *bev, <strong>void</strong> *ptr)
{
    <strong>char</strong> buf[1024];
    <strong>int</strong> n;
    <strong>struct</strong> evbuffer *input = bufferevent_get_input(bev);
    <strong>while</strong> ((n = evbuffer_remove(input, buf, <strong>sizeof</strong>(buf))) &gt; 0) {
        fwrite(buf, 1, n, stdout);
    }
}

<strong>void</strong> eventcb(<strong>struct</strong> bufferevent *bev, <strong>short</strong> events, <strong>void</strong> *ptr)
{
    <strong>if</strong> (events &amp; BEV_EVENT_CONNECTED) {
         printf("Connect okay.\n");
    } <strong>else</strong> <strong>if</strong> (events &amp; (BEV_EVENT_ERROR|BEV_EVENT_EOF)) {
         <strong>struct</strong> event_base *base = ptr;
         <strong>if</strong> (events &amp; BEV_EVENT_ERROR) {
                 <strong>int</strong> err = bufferevent_socket_get_dns_error(bev);
                 <strong>if</strong> (err)
                         printf("DNS error: %s\n", evutil_gai_strerror(err));
         }
         printf("Closing\n");
         bufferevent_free(bev);
         event_base_loopexit(base, NULL);
    }
}

<strong>int</strong> main(<strong>int</strong> argc, <strong>char</strong> **argv)
{
    <strong>struct</strong> event_base *base;
    <strong>struct</strong> evdns_base *dns_base;
    <strong>struct</strong> bufferevent *bev;

    <strong>if</strong> (argc != 3) {
        printf("Trivial HTTP 0.x client\n"
               "Syntax: %s [hostname] [resource]\n"
               "Example: %s www.google.com /\n",argv[0],argv[0]);
        <strong>return</strong> 1;
    }

    base = event_base_new();
    dns_base = evdns_base_new(base, 1);

    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, readcb, NULL, eventcb, base);
    bufferevent_enable(bev, EV_READ|EV_WRITE);
    evbuffer_add_printf(bufferevent_get_output(bev), "GET %s\r\n", argv[2]);
    bufferevent_socket_connect_hostname(
        bev, dns_base, AF_UNSPEC, argv[1], 80);
    event_base_dispatch(base);
    <strong>return</strong> 0;
}</tt></pre>
</div></div>
<div class="paragraph"><p>The bufferevent_socket_connect_hostname() function was new in Libevent
2.0.3-alpha; bufferevent_socket_get_dns_error() was new in 2.0.5-beta.</p></div>
<h3 id="_generic_bufferevent_operations">Generic bufferevent operations</h3><div style="clear:left"></div>
<div class="paragraph"><p>The functions in this section work with multiple bufferevent
implementations.</p></div>
<h4 id="_freeing_a_bufferevent">Freeing a bufferevent</h4>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>void</strong> bufferevent_free(<strong>struct</strong> bufferevent *bev);</tt></pre>
</div></div>
<div class="paragraph"><p>This function frees a bufferevent.  Bufferevents are internally
reference-counted, so if the bufferevent has pending deferred
callbacks when you free it, it won&#8217;t be deleted until the callbacks
are done.</p></div>
<div class="paragraph"><p>The bufferevent_free() function does, however, try to free the
bufferevent as soon as possible.  If there is pending data to write on
the bufferevent, it probably won&#8217;t be flushed before the bufferevent is
freed.</p></div>
<div class="paragraph"><p>If the BEV_OPT_CLOSE_ON_FREE flag was set, and this bufferevent has a
socket or underlying bufferevent associated with it as its transport,
that transport is closed when you free the bufferevent.</p></div>
<div class="paragraph"><p>This function was introduced in Libevent 0.8.</p></div>
<h4 id="_manipulating_callbacks_watermarks_and_enabled_operations">Manipulating callbacks, watermarks, and enabled operations</h4>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>typedef</strong> <strong>void</strong> (*bufferevent_data_cb)(<strong>struct</strong> bufferevent *bev, <strong>void</strong> *ctx);
<strong>typedef</strong> <strong>void</strong> (*bufferevent_event_cb)(<strong>struct</strong> bufferevent *bev,
    <strong>short</strong> events, <strong>void</strong> *ctx);

<strong>void</strong> bufferevent_setcb(<strong>struct</strong> bufferevent *bufev,
    bufferevent_data_cb readcb, bufferevent_data_cb writecb,
    bufferevent_event_cb eventcb, <strong>void</strong> *cbarg);

<strong>void</strong> bufferevent_getcb(<strong>struct</strong> bufferevent *bufev,
    bufferevent_data_cb *readcb_ptr,
    bufferevent_data_cb *writecb_ptr,
    bufferevent_event_cb *eventcb_ptr,
    <strong>void</strong> **cbarg_ptr);</tt></pre>
</div></div>
<div class="paragraph"><p>The bufferevent_setcb() function changes one or more of the callbacks
of a bufferevent.  The readcb, writecb, and eventcb functions are
called (respectively) when enough data is read, when enough data is
written, or when an event occurs.  The first argument of each is the
bufferevent that has had the event happen.  The last argument is the
value provided by the user in the <em>cbarg</em> parameter of
bufferevent_callcb(): You can use this to pass data to your
callbacks.  The <em>events</em> argument of the event callback is a bitmask
of event flags: see "callbacks and watermarks" above.</p></div>
<div class="paragraph"><p>You can disable a callback by passing NULL instead of the callback
function.  Note all the callback functions on a bufferevent share a
single <em>cbarg</em> value, so changing it will affect all of them.</p></div>
<div class="paragraph"><p>You can retrieve the currently set callbacks for a bufferevent by passing
pointers to bufferevent_getcb(), which sets *readcb_ptr to the current read
callback, *writecb_ptr to the current write callback, *eventcb_ptr to the
current event callback, and *cbarg_ptr to the current callback argument
field.  Any of these pointers set to NULL will be ignored.</p></div>
<div class="paragraph"><p>The bufferevent_setcb() function was introduced in Libevent 1.4.4.  The type
names "bufferevent_data_cb" and "bufferevent_event_cb" were new in Libevent
2.0.2-alpha.  The bufferevent_getcb() function was added in 2.1.1-alpha.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>void</strong> bufferevent_enable(<strong>struct</strong> bufferevent *bufev, <strong>short</strong> events);
<strong>void</strong> bufferevent_disable(<strong>struct</strong> bufferevent *bufev, <strong>short</strong> events);

<strong>short</strong> bufferevent_get_enabled(<strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>You can enable or disable the events EV_READ, EV_WRITE, or
EV_READ|EV_WRITE on a bufferevent.  When reading or writing is not
enabled, the bufferevent will not try to read or write data.</p></div>
<div class="paragraph"><p>There is no need to disable writing when the output buffer is empty:
the bufferevent automatically stops writing, and restarts again
when there is data to write.</p></div>
<div class="paragraph"><p>Similarly, there is no need to disable reading when the input buffer
is up to its high-water mark: the bufferevent automatically stops
reading, and restarts again when there is space to read.</p></div>
<div class="paragraph"><p>By default, a newly created bufferevent has writing enabled, but not
reading.</p></div>
<div class="paragraph"><p>You can call bufferevent_get_enabled() to see which events are currently
enabled on the bufferevent.</p></div>
<div class="paragraph"><p>These functions were introduced in Libevent 0.8, except for
bufferevent_get_enabled(), which was introduced in version 2.0.3-alpha.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>void</strong> bufferevent_setwatermark(<strong>struct</strong> bufferevent *bufev, <strong>short</strong> events,
    size_t lowmark, size_t highmark);</tt></pre>
</div></div>
<div class="paragraph"><p>The bufferevent_setwatermark() function adjusts the read watermarks,
the write watermarks, or both, of a single bufferevent.  (If EV_READ
is set in the events field, the read watermarks are adjusted.  If
EV_WRITE is set in the events field, the write watermarks are adjusted.)</p></div>
<div class="paragraph"><p>A high-water mark of 0 is equivalent to "unlimited".</p></div>
<div class="paragraph"><p>This function was first exposed in Libevent 1.4.4.</p></div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre><tt>#include &lt;event2/event.h&gt;
#include &lt;event2/bufferevent.h&gt;
#include &lt;event2/buffer.h&gt;
#include &lt;event2/util.h&gt;

#include &lt;stdlib.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;

<strong>struct</strong> info {
    <strong>const</strong> <strong>char</strong> *name;
    size_t total_drained;
};

<strong>void</strong> read_callback(<strong>struct</strong> bufferevent *bev, <strong>void</strong> *ctx)
{
    <strong>struct</strong> info *inf = ctx;
    <strong>struct</strong> evbuffer *input = bufferevent_get_input(bev);
    size_t len = evbuffer_get_length(input);
    <strong>if</strong> (len) {
        inf-&gt;total_drained += len;
        evbuffer_drain(input, len);
        printf("Drained %lu bytes from %s\n",
             (<strong>unsigned</strong> <strong>long</strong>) len, inf-&gt;name);
    }
}

<strong>void</strong> event_callback(<strong>struct</strong> bufferevent *bev, <strong>short</strong> events, <strong>void</strong> *ctx)
{
    <strong>struct</strong> info *inf = ctx;
    <strong>struct</strong> evbuffer *input = bufferevent_get_input(bev);
    <strong>int</strong> finished = 0;

    <strong>if</strong> (events &amp; BEV_EVENT_EOF) {
        size_t len = evbuffer_get_length(input);
        printf("Got a close from %s.  We drained %lu bytes from it, "
            "and have %lu left.\n", inf-&gt;name,
            (<strong>unsigned</strong> <strong>long</strong>)inf-&gt;total_drained, (<strong>unsigned</strong> <strong>long</strong>)len);
        finished = 1;
    }
    <strong>if</strong> (events &amp; BEV_EVENT_ERROR) {
        printf("Got an error from %s: %s\n",
            inf-&gt;name, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
        finished = 1;
    }
    <strong>if</strong> (finished) {
        free(ctx);
        bufferevent_free(bev);
    }
}

<strong>struct</strong> bufferevent *setup_bufferevent(<strong>void</strong>)
{
    <strong>struct</strong> bufferevent *b1 = NULL;
    <strong>struct</strong> info *info1;

    info1 = malloc(<strong>sizeof</strong>(<strong>struct</strong> info));
    info1-&gt;name = "buffer 1";
    info1-&gt;total_drained = 0;

<i>    /* ... Here we should set up the bufferevent and make sure it gets</i>
<i>       connected... */</i>

<i>    /* Trigger the read callback only whenever there is at least 128 bytes</i>
<i>       of data in the buffer. */</i>
    bufferevent_setwatermark(b1, EV_READ, 128, 0);

    bufferevent_setcb(b1, read_callback, NULL, event_callback, info1);

    bufferevent_enable(b1, EV_READ); /* Start reading. */
    <strong>return</strong> b1;
}</tt></pre>
</div></div>
<h4 id="_manipulating_data_in_a_bufferevent">Manipulating data in a bufferevent</h4>
<div class="paragraph"><p>Reading and writing data from the network does you no good if you
can&#8217;t look at it.  Bufferevents give you these methods to give them
data to write, and to get the data to read:</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>struct</strong> evbuffer *bufferevent_get_input(<strong>struct</strong> bufferevent *bufev);
<strong>struct</strong> evbuffer *bufferevent_get_output(<strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>These two functions are very powerful fundamental: they return the
input and output buffers respectively.  For full information on all
the operations you can perform on an evbuffer type, see the next
chapter.</p></div>
<div class="paragraph"><p>Note that the application may only remove (not add) data on the input
buffer, and may only add (not remove) data from the output buffer.</p></div>
<div class="paragraph"><p>If writing on the bufferevent was stalled because of too little data
(or if reading was stalled because of too much), then adding data to
the output buffer (or removing data from the input buffer) will
automatically restart it.</p></div>
<div class="paragraph"><p>These functions were introduced in Libevent 2.0.1-alpha.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>int</strong> bufferevent_write(<strong>struct</strong> bufferevent *bufev,
    <strong>const</strong> <strong>void</strong> *data, size_t size);
<strong>int</strong> bufferevent_write_buffer(<strong>struct</strong> bufferevent *bufev,
    <strong>struct</strong> evbuffer *buf);</tt></pre>
</div></div>
<div class="paragraph"><p>These functions add data to a bufferevent&#8217;s output buffer.  Calling
bufferevent_write() adds <em>size</em> bytes from the memory at <em>data</em> to the
end of the output buffer.  Calling bufferevent_write_buffer() removes
the entire contents of <em>buf</em> and puts them at the end of the output
buffer.   Both return 0 if successful, or -1 if an error occurred.</p></div>
<div class="paragraph"><p>These functions have existed since Libevent 0.8.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt>size_t bufferevent_read(<strong>struct</strong> bufferevent *bufev, <strong>void</strong> *data, size_t size);
<strong>int</strong> bufferevent_read_buffer(<strong>struct</strong> bufferevent *bufev,
    <strong>struct</strong> evbuffer *buf);</tt></pre>
</div></div>
<div class="paragraph"><p>These functions remove data from a bufferevent&#8217;s input buffer.  The
bufferevent_read() function removes up to <em>size</em> bytes from the input
buffer, storing them into the memory at <em>data</em>.  It returns the number
of bytes actually removed.  The bufferevent_read_buffer() function
drains the entire contents of the input buffer and places them into
<em>buf</em>; it returns 0 on success and -1 on failure.</p></div>
<div class="paragraph"><p>Note that with bufferevent_read(), the memory chunk at <em>data</em> must
actually have enough space to hold <em>size</em> bytes of data.</p></div>
<div class="paragraph"><p>The bufferevent_read() function has existed since Libevent 0.8;
bufferevent_read_buffer() was introduced in Libevent 2.0.1-alpha.</p></div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre><tt>#include &lt;event2/bufferevent.h&gt;
#include &lt;event2/buffer.h&gt;

#include &lt;ctype.h&gt;

<strong>void</strong>
read_callback_uppercase(<strong>struct</strong> bufferevent *bev, <strong>void</strong> *ctx)
{
<i>        /* This callback removes the data from bev's input buffer 128</i>
<i>           bytes at a time, uppercases it, and starts sending it</i>
<i>           back.</i>

<i>           (Watch out!  In practice, you shouldn't use toupper to implement</i>
<i>           a network protocol, unless you know for a fact that the current</i>
<i>           locale is the one you want to be using.)</i>
<i>         */</i>

        <strong>char</strong> tmp[128];
        size_t n;
        <strong>int</strong> i;
        <strong>while</strong> (1) {
                n = bufferevent_read(bev, tmp, <strong>sizeof</strong>(tmp));
                <strong>if</strong> (n &lt;= 0)
                        <strong>break</strong>; /* No more data. */
                <strong>for</strong> (i=0; i&lt;n; ++i)
                        tmp[i] = toupper(tmp[i]);
                bufferevent_write(bev, tmp, n);
        }
}

<strong>struct</strong> proxy_info {
        <strong>struct</strong> bufferevent *other_bev;
};
<strong>void</strong>
read_callback_proxy(<strong>struct</strong> bufferevent *bev, <strong>void</strong> *ctx)
{
<i>        /* You might use a function like this if you're implementing</i>
<i>           a simple proxy: it will take data from one connection (on</i>
<i>           bev), and write it to another, copying as little as</i>
<i>           possible. */</i>
        <strong>struct</strong> proxy_info *inf = ctx;

        bufferevent_read_buffer(bev,
            bufferevent_get_output(inf-&gt;other_bev));
}

<strong>struct</strong> count {
        <strong>unsigned</strong> <strong>long</strong> last_fib[2];
};

<strong>void</strong>
write_callback_fibonacci(<strong>struct</strong> bufferevent *bev, <strong>void</strong> *ctx)
{
<i>        /* Here's a callback that adds some Fibonacci numbers to the</i>
<i>           output buffer of bev.  It stops once we have added 1k of</i>
<i>           data; once this data is drained, we'll add more. */</i>
        <strong>struct</strong> count *c = ctx;

        <strong>struct</strong> evbuffer *tmp = evbuffer_new();
        <strong>while</strong> (evbuffer_get_length(tmp) &lt; 1024) {
                 <strong>unsigned</strong> <strong>long</strong> next = c-&gt;last_fib[0] + c-&gt;last_fib[1];
                 c-&gt;last_fib[0] = c-&gt;last_fib[1];
                 c-&gt;last_fib[1] = next;

                 evbuffer_add_printf(tmp, "%lu", next);
        }

<i>        /* Now we add the whole contents of tmp to bev. */</i>
        bufferevent_write_buffer(bev, tmp);

<i>        /* We don't need tmp any longer. */</i>
        evbuffer_free(tmp);
}</tt></pre>
</div></div>
<h4 id="_read_and_write_timeouts">Read- and write timeouts</h4>
<div class="paragraph"><p>As with other events, you can have a timeout get invoked if a certain
amount of time passes without any data having been successfully
written or read by a bufferevent.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>void</strong> bufferevent_set_timeouts(<strong>struct</strong> bufferevent *bufev,
    <strong>const</strong> <strong>struct</strong> timeval *timeout_read, <strong>const</strong> <strong>struct</strong> timeval *timeout_write);</tt></pre>
</div></div>
<div class="paragraph"><p>Setting a timeout to NULL is supposed to remove it; however before Libevent
2.1.2-alpha this wouldn&#8217;t work with all event types.  (As a workaround for
older versions, you can try setting the timeout to a multi-day interval
and/or having your eventcb function ignore BEV_TIMEOUT events when you don&#8217;t
want them.)</p></div>
<div class="paragraph"><p>The read timeout will trigger if the bufferevent waits at least
<em>timeout_read</em> seconds while trying to read read.  The write
timeout will trigger if the bufferevent waits at least <em>timeout_write</em>
seconds while trying to write data.</p></div>
<div class="paragraph"><p>Note that the timeouts only count when the bufferevent would like to
read or write.  In other words, the read timeout is not enabled if
reading is disabled on the bufferevent, or if the input buffer is full
(at its high-water mark).  Similarly, the write timeout is not enabled if
if writing is disabled, or if there is no data to write.</p></div>
<div class="paragraph"><p>When a read or write timeout occurs, the corresponding read or write
operation becomes disabled on the bufferevent.  The event callback is then
invoked with either BEV_EVENT_TIMEOUT|BEV_EVENT_READING or
BEV_EVENT_TIMEOUT|BEV_EVENT_WRITING.</p></div>
<div class="paragraph"><p>This functions has existed since Libevent 2.0.1-alpha.  It didn&#8217;t behave
consistently across bufferevent types until Libevent 2.0.4-alpha.</p></div>
<h4 id="_initiating_a_flush_on_a_bufferevent">Initiating a flush on a bufferevent</h4>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>int</strong> bufferevent_flush(<strong>struct</strong> bufferevent *bufev,
    <strong>short</strong> iotype, <strong>enum</strong> bufferevent_flush_mode state);</tt></pre>
</div></div>
<div class="paragraph"><p>Flushing a bufferevent tells the bufferevent to force as many bytes
as possible to be read to or written from the underlying transport,
ignoring other restrictions that might otherwise keep them from
being written.  Its detailed function depends on the type of the
bufferevent.</p></div>
<div class="paragraph"><p>The iotype argument should be EV_READ, EV_WRITE, or EV_READ|EV_WRITE to
indicate whether bytes being read, written, or both should be
processed.  The state argument may be one of BEV_NORMAL,
BEV_FLUSH, or BEV_FINISHED.  BEV_FINISHED indicates that the other
side should be told that no more data will be sent; the distinction
between BEV_NORMAL and BEV_FLUSH depends on the type of the
bufferevent.</p></div>
<div class="paragraph"><p>The bufferevent_flush() function returns -1 on failure, 0 if no data
was flushed, or 1 if some data was flushed.</p></div>
<div class="paragraph"><p>Currently (as of Libevent 2.0.5-beta), bufferevent_flush() is only
implemented for some bufferevent types.  In particular, socket-based
bufferevents don&#8217;t have it.</p></div>
<h3 id="_type_specific_bufferevent_functions">Type-specific bufferevent functions</h3><div style="clear:left"></div>
<div class="paragraph"><p>These bufferevent functions are not supported on all bufferevent
types.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>int</strong> bufferevent_priority_set(<strong>struct</strong> bufferevent *bufev, <strong>int</strong> pri);
<strong>int</strong> bufferevent_get_priority(<strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>This function adjusts the priority of the events used to implement
<em>bufev</em> to <em>pri</em>.  See event_priority_set() for more information on
priorities.</p></div>
<div class="paragraph"><p>This function returns 0 on success, and -1 on failure.  It works on
socket-based bufferevents only.</p></div>
<div class="paragraph"><p>The bufferevent_priority_set() function was introduced in Libevent 1.0;
bufferevent_get_priority() didn&#8217;t appear until Libevent 2.1.2-alpha.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>int</strong> bufferevent_setfd(<strong>struct</strong> bufferevent *bufev, evutil_socket_t fd);
evutil_socket_t bufferevent_getfd(<strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>These functions set or return the file descriptor for a fd-based
event.  Only socket-based bufferevents support setfd().  Both return
-1 on failure; setfd() returns 0 on success.</p></div>
<div class="paragraph"><p>The bufferevent_setfd() function was introduced in Libevent 1.4.4;
the bufferevent_getfd() function was introduced in Libevent 2.0.2-alpha.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>struct</strong> event_base *bufferevent_get_base(<strong>struct</strong> bufferevent *bev);</tt></pre>
</div></div>
<div class="paragraph"><p>This function returns the event_base of a bufferevent.  It was introduced in
2.0.9-rc.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>struct</strong> bufferevent *bufferevent_get_underlying(<strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>This function returns the bufferevent that another bufferevent is
using as a transport, if any.  For information on when this situation
would occur, see notes on filtering bufferevents.</p></div>
<div class="paragraph"><p>This function was introduced in Libevent 2.0.2-alpha.</p></div>
<h3 id="_manually_locking_and_unlocking_a_bufferevent">Manually locking and unlocking a bufferevent</h3><div style="clear:left"></div>
<div class="paragraph"><p>As with evbuffers, sometimes you want to ensure that a number of operations
on a bufferevent are all performed atomically.  Libevent exposes functions
that you can use to manually lock and unlock a bufferevent.</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>void</strong> bufferevent_lock(<strong>struct</strong> bufferevent *bufev);
<strong>void</strong> bufferevent_unlock(<strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>Note that locking a bufferevent has no effect if the bufferevent was not
given the BEV_OPT_THREADSAFE thread on creation, or if Libevent&#8217;s threading
support wasn&#8217;t activated.</p></div>
<div class="paragraph"><p>Locking the bufferevent with this function will lock its associated evbuffers
as well.  These functions are recursive: it is safe to lock a bufferevent for
which you already hold the lock.  You must, of course, call unlock once for
every time that you locked the bufferevent.</p></div>
<div class="paragraph"><p>These functions were introduced in Libevent 2.0.6-rc.</p></div>
<h3 id="_obsolete_bufferevent_functionality">Obsolete bufferevent functionality</h3><div style="clear:left"></div>
<div class="paragraph"><p>The bufferevent backend code underwent substantial revision between
Libevent 1.4 and Libevent 2.0.  In the old interface, it was sometimes
normal to build with access to the internals of the struct
bufferevent, and to use macros that relied on this access.</p></div>
<div class="paragraph"><p>To make matters confusing, the old code sometimes used names for
bufferevent functionality that were prefixed with "evbuffer".</p></div>
<div class="paragraph"><p>Here&#8217;s a brief guideline of what things used to be called before
Libevent 2.0:</p></div>
<div class="tableblock">
<table rules="all"
width="90%"
frame="border"
cellspacing="0" cellpadding="4">
<col width="50%" />
<col width="50%" />
<thead>
<tr>
<th align="left" valign="top"> Current name               </th>
<th align="left" valign="top"> Old name</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left" valign="top"><p class="table">bufferevent_data_cb</p></td>
<td align="left" valign="top"><p class="table">evbuffercb</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">bufferevent_event_cb</p></td>
<td align="left" valign="top"><p class="table">everrorcb</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">BEV_EVENT_READING</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_READ</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">BEV_EVENT_WRITE</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_WRITE</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">BEV_EVENT_EOF</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_EOF</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">BEV_EVENT_ERROR</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_ERROR</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">BEV_EVENT_TIMEOUT</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_TIMEOUT</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">bufferevent_get_input(b)</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_INPUT(b)</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">bufferevent_get_output(b)</p></td>
<td align="left" valign="top"><p class="table">EVBUFFER_OUTPUT(b)</p></td>
</tr>
</tbody>
</table>
</div>
<div class="paragraph"><p>The old functions were defined in event.h, not in event2/bufferevent.h.</p></div>
<div class="paragraph"><p>If you still need access to the internals of the common parts of the
bufferevent struct, you can include event2/bufferevent_struct.h.  We
recommend against it: the contents of struct bufferevent WILL change between
versions of Libevent.  The macros and names in this section are available if
you include event2/bufferevent_compat.h.</p></div>
<div class="paragraph"><p>The interface to set up a bufferevent differed in older versions:</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>struct</strong> bufferevent *bufferevent_new(evutil_socket_t fd,
    evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, <strong>void</strong> *cbarg);
<strong>int</strong> bufferevent_base_set(<strong>struct</strong> event_base *base, <strong>struct</strong> bufferevent *bufev);</tt></pre>
</div></div>
<div class="paragraph"><p>The bufferevent_new() function creates a socket bufferevent only, and does so
on the deprecated "default" event_base.  Calling bufferevent_base_set adjusts
the event_base of a socket bufferevent only.</p></div>
<div class="paragraph"><p>Instead of setting timeouts as struct timeval, they were set as
numbers of seconds:</p></div>
<div class="listingblock">
<div class="title">Interface</div>
<div class="content">
<pre><tt><strong>void</strong> bufferevent_settimeout(<strong>struct</strong> bufferevent *bufev,
    <strong>int</strong> timeout_read, <strong>int</strong> timeout_write);</tt></pre>
</div></div>
<div class="paragraph"><p>Finally, note that the underlying evbuffer implementation for Libevent
versions before 2.0 was pretty inefficient, to the point where using
bufferevents for high-performance apps was kind of questionable.</p></div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Last updated 2014-08-29 16:21:37 EDT
</div>
</div>
</body>
</html>
